﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x804 上介绍了“空白页”项模板


using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.UI.Core;
using System.Text;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using Windows.Devices.Bluetooth.Advertisement;

namespace App1
{
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        private bool ble_flag = false;
        private DeviceWatcher deviceWatcher = null;
        private BluetoothLEDevice bluetoothLeDevice = null;
        private string ble_id = null;
        private DeviceInformation deviceInformation = null;
        //private GattCharacteristic csc_characteristic;
        //private bool isValueChangedHandlerRegistered = false;
        //private GattPresentationFormat presentationFormat;
        DevicePairingResult result = null;
        private GattCharacteristic csc_characteristic = null;
        private BluetoothLEAdvertisementPublisher publisher;


        public MainPage()
        {
            this.InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //TextBox
            dev_watcher();
            //Test_ble();


        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            //testbox.Text += "abc";
            //var s = testbox.Text.Split("\n")[-1];
            //testbox1.Text = testbox.Text;
            //var text = testbox.Text;
            //var sp = text.Split("\n".ToCharArray());
            //testbox1.Text = sp[sp.Length -1];
            
        }

        private void testbox_TextChanged(object sender, RoutedEventArgs e)
        {
            //testbox.GetValue()
            //testbox.
            //testbox.Document

        }

        private void dev_watcher()
        {
            //EnumerateButton.Content = "Stop enumerating";

            // Additional properties we would like about the device.
            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" };

            // BT_Code: Currently Bluetooth APIs don't provide a selector to get ALL devices that are both paired and non-paired.
            deviceWatcher =
                    DeviceInformation.CreateWatcher(
                        "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")",
                        requestedProperties,
                        DeviceInformationKind.AssociationEndpoint);

            // Register event handlers before starting the watcher.
            deviceWatcher.Added += DeviceWatcher_Added;
            deviceWatcher.Updated += DeviceWatcher_Updated;
            deviceWatcher.Removed += DeviceWatcher_Removed;
            deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompletedAsync;
            deviceWatcher.Stopped += DeviceWatcher_Stopped;

            // Start over with an empty collection.
            //ResultCollection.Clear();

            // Start the watcher.
            deviceWatcher.Start();
        }


        ////private async void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        ////{
        ////    // BT_Code: An Indicate or Notify reported that the value has changed.
        ////    // Display the new value with a timestamp.
        ////    var newValue = FormatValueByPresentation(args.CharacteristicValue, presentationFormat);
        ////    var message = $"Value at {DateTime.Now:hh:mm:ss.FFF}: {newValue}";
        ////    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
        ////        () => CharacteristicLatestValue.Text = message);
        ////}

        ////private void AddValueChangedHandler()
        ////{
        ////    if (!isValueChangedHandlerRegistered)
        ////    {
        ////        csc_characteristic.ValueChanged += Characteristic_ValueChanged;
        ////        isValueChangedHandlerRegistered = true;
        ////    }
        ////}

        //private async void CharacteristicNotifyButton_Click()
        //{
        //    //try
        //    //{
        //    //    // BT_Code: Must write the CCCD in order for server to send notifications.
        //    //    // We receive them in the ValueChanged event handler.
        //    //    // Note that this sample configures either Indicate or Notify, but not both.
        //    //    var result = await
        //    //            csc_characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
        //    //                GattClientCharacteristicConfigurationDescriptorValue.Notify);
        //    //    if (result == GattCommunicationStatus.Success)
        //    //    {
        //    //        AddValueChangedHandler();
        //    //        rootPage.NotifyUser("Successfully registered for notifications", NotifyType.StatusMessage);
        //    //    }
        //    //    else
        //    //    {
        //    //        rootPage.NotifyUser($"Error registering for notifications: {result}", NotifyType.ErrorMessage);
        //    //    }
        //    //}
        //    //catch (UnauthorizedAccessException ex)
        //    //{
        //    //    // This usually happens when a device reports that it support notify, but it actually doesn't.
        //    //    rootPage.NotifyUser(ex.Message, NotifyType.ErrorMessage);
        //    //}
        //}


        private string FormatValueByPresentation(IBuffer buffer, GattPresentationFormat format)
        {
            // BT_Code: For the purpose of this sample, this function converts only UInt32 and
            // UTF-8 buffers to readable text. It can be extended to support other formats if your app needs them.
            byte[] data;
            CryptographicBuffer.CopyToByteArray(buffer, out data);
            if (format != null)
            {
                if (format.FormatType == GattPresentationFormatTypes.UInt32 && data.Length >= 4)
                {
                    return BitConverter.ToInt32(data, 0).ToString();
                }
                else if (format.FormatType == GattPresentationFormatTypes.Utf8)
                {
                    try
                    {
                        return Encoding.UTF8.GetString(data);
                    }
                    catch (ArgumentException)
                    {
                        return "(error: Invalid UTF-8 string)";
                    }
                }
                else
                {
                    // Add support for other format types as needed.
                    return "Unsupported format: " + CryptographicBuffer.EncodeToHexString(buffer);
                }
            }
            else
            {
                // We don't know what format to use. Let's try a well-known profile, or default back to UTF-8.
                if (csc_characteristic.Uuid.Equals(GattCharacteristicUuids.HeartRateMeasurement))
                {
                    try
                    {
                        return "lll";
                        //return "Heart Rate: " + ParseHeartRateValue(data).ToString();
                    }
                    catch (ArgumentException)
                    {
                        return "Heart Rate: (unable to parse)";
                    }
                }
                else if (csc_characteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel))
                {
                    try
                    {
                        // battery level is encoded as a percentage value in the first byte according to
                        // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml
                        return "Battery Level: " + data[0].ToString() + "%";
                    }
                    catch (ArgumentException)
                    {
                        return "Battery Level: (unable to parse)";
                    }
                }
                else
                {
                    try
                    {
                        return "Unknown format: " + Encoding.UTF8.GetString(data);
                    }
                    catch (ArgumentException)
                    {
                        return "Unknown format";
                    }
                }
            }
        }

        private async void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
        {
            // BT_Code: An Indicate or Notify reported that the value has changed.
            // Display the new value with a timestamp.
            //var newValue = FormatValueByPresentation(args.CharacteristicValue, presentationFormat);
            var newValue = FormatValueByPresentation(args.CharacteristicValue, null);

            var message = $"Value at {DateTime.Now:hh:mm:ss.FFF}: {newValue}";
            //await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            //    () => CharacteristicLatestValue.Text = message);
            
            //await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => testbox.Text += message);

        }

        private async void register_val_cb()
        {
            var result = await
                    csc_characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(
                        GattClientCharacteristicConfigurationDescriptorValue.Notify);
            if (result == GattCommunicationStatus.Success)
            {
                //if (!isValueChangedHandlerRegistered)
                //{
                    csc_characteristic.ValueChanged += Characteristic_ValueChanged;
                    //isValueChangedHandlerRegistered = true;
                //}
                
            }

        }

        private void ClearBluetoothLEDevice()
        {
            bluetoothLeDevice?.Dispose();
            bluetoothLeDevice = null;
        }

        public void show_char(GattCharacteristic charct)
        {
            testbox1.Text += charct.Uuid + "\n";

            if (charct.Uuid.ToString() == "fd5abba1-3935-11e5-85a6-0002a5d5c51b")
            {
                testbox.Text += "find cussssss";
                csc_characteristic = charct;
                register_val_cb();


            }
        }

        private void show_service(GattDeviceService service)
        {
            testbox.Text += service.Uuid + "\n";
            testbox1.Text += "----------------\n";

            //service.

            IReadOnlyList<GattCharacteristic> characteristics = null;
            try
            {
                // BT_Code: Get all the child characteristics of a service.
                characteristics = service.GetAllCharacteristics();
            }
            catch (Exception ex)
            {
                //rootPage.NotifyUser("Restricted service. Can't read characteristics: " + ex.Message,
                //    NotifyType.ErrorMessage);
                // On error, act as if there are no characteristics.
                characteristics = new List<GattCharacteristic>();
                testbox1.Text += "error: " + ex.Message + "\n";
            }

            foreach (var charct in characteristics)
            {
                show_char(charct);
            }

        }
        private async void pair()
        {
            //// Do not allow a new Pair operation to start if an existing one is in progress.
            ////if (isBusy)
            ////{
            ////    return;
            ////}

            ////isBusy = true;

            ////rootPage.NotifyUser("Pairing started. Please wait...", NotifyType.StatusMessage);

            //// For more information about device pairing, including examples of
            //// customizing the pairing process, see the DeviceEnumerationAndPairing sample.

            //// Capture the current selected item in case the user changes it while we are pairing.
            //var bleDeviceDisplay = ResultsListView.SelectedItem as BluetoothLEDeviceDisplay;

            //// BT_Code: Pair the currently selected device.
            //DevicePairingResult result = await bleDeviceDisplay.DeviceInformation.Pairing.PairAsync();
            //rootPage.NotifyUser($"Pairing result = {result.Status}",
            //    result.Status == DevicePairingResultStatus.Paired || result.Status == DevicePairingResultStatus.AlreadyPaired
            //        ? NotifyType.StatusMessage
            //        : NotifyType.ErrorMessage);

            //isBusy = false;

            //DevicePairingResult result = await 

            testbox.Text = deviceInformation.Pairing.CanPair.ToString();
            testbox.Text += deviceInformation.Pairing.IsPaired.ToString();
            var custom_p = deviceInformation.Pairing.Custom;
            

            System.Diagnostics.Debug.WriteLine("this is test hello\n");
            custom_p.PairingRequested += PairingRequestedHandler;
            //deviceInformation.Kind.p
            //DevicePairingKinds pkind =  ;
            //DevicePairingResult result = await custom_p.PairAsync(DevicePairingKinds.DisplayPin | DevicePairingKinds.ConfirmPinMatch);
            result = await custom_p.PairAsync(DevicePairingKinds.ProvidePin, DevicePairingProtectionLevel.None);
            custom_p.PairingRequested -= PairingRequestedHandler;
            //DevicePairingKinds.
            //custom_p.pa
            //custom_p.PairingRequested

            //deviceInformation.Pairing.PairAsync();
            System.Diagnostics.Debug.WriteLine("llllllllll");
            System.Diagnostics.Debug.WriteLine(result.Status);

            //if (result.Status == DevicePairingResultStatus.Paired || result.Status == DevicePairingResultStatus.AlreadyPaired)
            //{
            //    await deviceInformation.Pairing.UnpairAsync();
            //}

        }

        private void notify()
        {
            //var descriptors = csc_characteristic.GetAllDescriptors();
        }

        private async void unpair()
        {
            if (result.Status == DevicePairingResultStatus.Paired || result.Status == DevicePairingResultStatus.AlreadyPaired)
            {
                await deviceInformation.Pairing.UnpairAsync();
            }
        }
        private async void PairingRequestedHandler(
            DeviceInformationCustomPairing sender,
            DevicePairingRequestedEventArgs args)
        {
            //testbox.Text += "lllllllleeeeeeeeeeeee\n";
            //System.Diagnostics.Debug.WriteLine("custome pair....");
            args.Accept("123456");
            //switch (args.PairingKind)
            //{
            //    case DevicePairingKinds.ConfirmOnly:
            //        // Windows itself will pop the confirmation dialog as part of "consent" if this is running on Desktop or Mobile
            //        // If this is an App for 'Windows IoT Core' where there is no Windows Consent UX, you may want to provide your own confirmation.
            //        args.Accept();
            //        break;

            //    case DevicePairingKinds.DisplayPin:
            //        // We just show the PIN on this side. The ceremony is actually completed when the user enters the PIN
            //        // on the target device. We automatically accept here since we can't really "cancel" the operation
            //        // from this side.
            //        args.Accept();

            //        // No need for a deferral since we don't need any decision from the user
            //        await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            //        {
            //            ShowPairingPanel(
            //                "Please enter this PIN on the device you are pairing with: " + args.Pin,
            //                args.PairingKind);

            //        });
            //        break;

            //    case DevicePairingKinds.ProvidePin:
            //        // A PIN may be shown on the target device and the user needs to enter the matching PIN on 
            //        // this Windows device. Get a deferral so we can perform the async request to the user.
            //        var collectPinDeferral = args.GetDeferral();

            //        await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            //        {
            //            string pin = await GetPinFromUserAsync();
            //            if (!string.IsNullOrEmpty(pin))
            //            {
            //                args.Accept(pin);
            //            }

            //            collectPinDeferral.Complete();
            //        });
            //        break;

            //    case DevicePairingKinds.ConfirmPinMatch:
            //        // We show the PIN here and the user responds with whether the PIN matches what they see
            //        // on the target device. Response comes back and we set it on the PinComparePairingRequestedData
            //        // then complete the deferral.
            //        var displayMessageDeferral = args.GetDeferral();

            //        await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            //        {
            //            bool accept = await GetUserConfirmationAsync(args.Pin);
            //            if (accept)
            //            {
            //                args.Accept();
            //            }

            //            displayMessageDeferral.Complete();
            //        });
            //        break;
            //}
        }

        private async void Test_ble()
        {
            ClearBluetoothLEDevice();

            if (ble_flag == false)
            {
                //var ble_id = "BluetoothLE#BluetoothLE14:2d:27:f5:c1:6e-f8:f0:05:f3:5e:5f";
                if (ble_id == null)
                {
                    testbox.Text = "null id";
                    return;
                }
                testbox.Text = ble_id + "\n";
                //bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(rootPage.SelectedBleDeviceId);
                bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(ble_id);
                //bluetoothLeDevice = await BluetoothLEDevice.from
                //BluetoothLEDevice.FromHostNameAsync();
                
                //var remoteDevice = await BluetoothDevice.FromHostNameAsync(socket.Information.RemoteHostName);

                // testbox1.Text = bluetoothLeDevice.ToString();
                if (bluetoothLeDevice != null)
                {
                    testbox.Text = "";
                    testbox1.Text = "";
                    testbox.Text = "connect true";


                    testbox.Text += bluetoothLeDevice.ConnectionStatus;
                    //bluetoothLeDevice.

                    // BT_Code: GattServices returns a list of all the supported services of the device.
                    // If the services supported by the device are expected to change
                    // during BT usage, subscribe to the GattServicesChanged event.

                    foreach (var service in bluetoothLeDevice.GattServices)
                    {
                        show_service(service);
                        //testbox.Text += service.ToString();

                        //testbox1.Text += service.Uuid + "\n";
                        //switch(service.cha)
                        //testbox1.Text += service.
                        //foreach (var crt in service.GetAllCharacteristics())
                        //{
                        //    var val = crt.ReadValueAsync();
                        //    //var rst = val.GetResults();
                        //    //testbox.Text = rst.Value.ToString();

                        //    testbox1.Text += val.ToString() + "\n";
                        //}
                        //ServiceCollection.Add(new BluetoothLEAttributeDisplay(service));
                    }
                    //ConnectButton.Visibility = Visibility.Collapsed;
                    //ServiceList.Visibility = Visibility.Visible;
                }
                else
                {
                    testbox.Text = "connect false";
                    //testbox.Text = NotifyType.ErrorMessage;
                }
            }
            //testbox1.Text += "a";
        }

        private void testbox_TextChanged_1(object sender, TextChangedEventArgs e)
        {
            //testbox.Text += "abc";
            //var s = testbox.Text.Split("\n")[-1];
            //testbox1.Text = testbox.Text;
            //var text = testbox.Text;
            ////var text = "abc\nweasdfasd";
            ////char[] k = ['\n'];
            //var sp = text.Split('\r');

            //testbox1.Text = sp.Length.ToString();
            //testbox1.Text = sp[sp.Length - 1] + sp.Length.ToString();
            //testbox1.Text = sp.ToString();
            //Test_ble();
        }

        private async void conn_bt_Click(object sender, RoutedEventArgs e)
        {
            Test_ble();
        }

        private async void unpair_bt_Click(object sender, RoutedEventArgs e)
        {
            unpair();
        }

        private async void pair_bt_Click(object sender, RoutedEventArgs e)
        {
            pair();
        }

        private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
        {
            //var service = await GattDeviceService.FromIdAsync(args.Id);
            //if (service != null)
            //{
            //    switch (service.Uuid.ToString())
            //    {
            //        case SensorUUIDs.UUID_ENV_SERV:
            //            InitializeTemperatureSensor(service);
            //            InitializePressureSensor(service);
            //            break;
            //        case SensorUUIDs.UUID_ACC_SERV:
            //            InitializeAccelerationSensor(service);
            //            break;
            //    }
            //}

            // We must update the collection on the UI thread because the collection is databound to a UI element.
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                // Protect against race condition if the task runs after the app stopped the deviceWatcher.
                if (sender == deviceWatcher)
                {
                    testbox1.Text += deviceInfo.Id;
                    ble_id = deviceInfo.Id;
                    deviceInformation = deviceInfo;
                    //// Make sure device name isn't blank or already present in the list.
                    //if (deviceInfo.Name != string.Empty && FindBluetoothLEDeviceDisplay(deviceInfo.Id) == null)
                    //{
                    //    ResultCollection.Add(new BluetoothLEDeviceDisplay(deviceInfo));
                    //}
                }
            });
        }

        private async void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
        {
            //// We must update the collection on the UI thread because the collection is databound to a UI element.
            //await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            //{
            //    // Protect against race condition if the task runs after the app stopped the deviceWatcher.
            //    if (sender == deviceWatcher)
            //    {
            //        BluetoothLEDeviceDisplay bleDeviceDisplay = FindBluetoothLEDeviceDisplay(deviceInfoUpdate.Id);
            //        if (bleDeviceDisplay != null)
            //        {
            //            bleDeviceDisplay.Update(deviceInfoUpdate);
            //        }
            //    }
            //});
        }

        private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
        {
            //// We must update the collection on the UI thread because the collection is databound to a UI element.
            //await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            //{
            //    // Protect against race condition if the task runs after the app stopped the deviceWatcher.
            //    if (sender == deviceWatcher)
            //    {
            //        // Find the corresponding DeviceInformation in the collection and remove it.
            //        BluetoothLEDeviceDisplay bleDeviceDisplay = FindBluetoothLEDeviceDisplay(deviceInfoUpdate.Id);
            //        if (bleDeviceDisplay != null)
            //        {
            //            ResultCollection.Remove(bleDeviceDisplay);
            //        }
            //    }
            //});
        }

        private async void DeviceWatcher_EnumerationCompletedAsync(DeviceWatcher sender, object e)
        {
            // We must update the collection on the UI thread because the collection is databound to a UI element.
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                // Protect against race condition if the task runs after the app stopped the deviceWatcher.
                if (sender == deviceWatcher)
                {
                    //rootPage.NotifyUser($"{ResultCollection.Count} devices found. Enumeration completed.",
                    //    NotifyType.StatusMessage);
                }
            });
        }

        private async void DeviceWatcher_Stopped(DeviceWatcher sender, object e)
        {
            //// We must update the collection on the UI thread because the collection is databound to a UI element.
            //await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            //{
            //    // Protect against race condition if the task runs after the app stopped the deviceWatcher.
            //    if (sender == deviceWatcher)
            //    {
            //        rootPage.NotifyUser($"No longer watching for devices.",
            //                sender.Status == DeviceWatcherStatus.Aborted ? NotifyType.ErrorMessage : NotifyType.StatusMessage);
            //    }
            //});
        }


        //private async void CharacteristicWriteButton_Click()
        //{
        //    if (!String.IsNullOrEmpty(CharacteristicWriteValue.Text))
        //    {
        //        var writeBuffer = CryptographicBuffer.ConvertStringToBinary(CharacteristicWriteValue.Text,
        //            BinaryStringEncoding.Utf8);
        //        try
        //        {
        //            // BT_Code: Writes the value from the buffer to the characteristic.
        //            var result = await selectedCharacteristic.WriteValueAsync(writeBuffer);

        //            if (result == GattCommunicationStatus.Success)
        //            {
        //                rootPage.NotifyUser("Successfully wrote value to device", NotifyType.StatusMessage);
        //            }
        //            else
        //            {
        //                rootPage.NotifyUser($"Write failed: {result}", NotifyType.ErrorMessage);
        //            }
        //        }
        //        catch (Exception ex) when ((uint)ex.HResult == 0x80650003 || (uint)ex.HResult == 0x80070005)
        //        {
        //            // E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED or E_ACCESSDENIED
        //            // This usually happens when a device reports that it support writing, but it actually doesn't.
        //            rootPage.NotifyUser(ex.Message, NotifyType.ErrorMessage);
        //        }
        //    }
        //    else
        //    {
        //        rootPage.NotifyUser("No data to write to device", NotifyType.ErrorMessage);
        //    }
        //}


        private async void testbox1_Copy_TextChanged(object sender, TextChangedEventArgs e)
        {
            var box = (TextBox)sender;
            //var box = testbox2;
            if (csc_characteristic != null)
            {
                var cary = box.Text.ToCharArray();
                if (cary.Count() > 0 && (cary[cary.Length-1] == '\n' || cary[cary.Length - 1] == '\r'))
                {
                    //using (InMemoryRandomAccessStream memoryStream = new InMemoryRandomAccessStream())
                    //{
                    //    using (DataWriter dataWriter = new DataWriter(memoryStream))
                    //    {
                    //        dataWriter.WriteString(str);
                    //        return dataWriter.DetachBuffer();
                    //    }
                    //}
                    //IBuffer
                    //var buf = Windows.Storage.Streams.Buffer.CreateMemoryBufferOverIBuffer(;
                    //WindowsRuntimeBufferExtensions.AsBuffer(cary, 0, cary.Length);

                    //var memstream = new InMemoryRandomAccessStream();
                    //var datawriter = new DataWriter(memstream);
                    //datawriter.WriteString(box.Text);
                    //var buf = datawriter.DetachBuffer();
                    var buf = CryptographicBuffer.ConvertStringToBinary(box.Text, BinaryStringEncoding.Utf8);

                //    SetVisibility(CharacteristicWritePanel,
                //properties.HasFlag(GattCharacteristicProperties.Write) ||
                //properties.HasFlag(GattCharacteristicProperties.WriteWithoutResponse));

                    if (csc_characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Write))
                    {
                        testbox.Text += "have write properties";
                    }
                    else
                    {
                        testbox.Text += "charact no write properties";
                        return;
                    }

                    //csc_characteristic.Nodify

                    //csc_characteristic.ReadClientCharacteristicConfigurationDescriptorAsync

                    //csc_characteristic.WriteClientCharacteristicConfigurationDescriptorAsync()
                    var result = await csc_characteristic.WriteValueAsync(buf);
                    //testbox1.Text = result.ProtocolError.Value.ToString();

                    if (result == GattCommunicationStatus.Success)
                    {
                        testbox.Text = "send ok";

                    }
                    else
                    {
                        testbox.Text = "send faild";
                    }
                    //bluetoothLeDevice.
                        //await csc_characteristic.WriteValueAsync(buf);
                        //testbox1.Text = box.Text;
                        //testbox1.Text += buf.ToString();
                        //using (DataReader dataReader = DataReader.FromBuffer(buffer))
                        //{
                        //    return dataReader.ReadString(buffer.Length);
                        //}
                        var dr = DataReader.FromBuffer(buf);
                    var s = dr.ReadString(buf.Length);
                    testbox1.Text += s;

                }
            }
        }

        private void publisher_cb()
        {

            // Create and initialize a new publisher instance.
            publisher = new BluetoothLEAdvertisementPublisher();

            // We need to add some payload to the advertisement. A publisher without any payload
            // or with invalid ones cannot be started. We only need to configure the payload once
            // for any publisher.

            // Add a manufacturer-specific section:
            // First, let create a manufacturer data section
            var manufacturerData = new BluetoothLEManufacturerData();

            // Then, set the company ID for the manufacturer data. Here we picked an unused value: 0xFFFE
            manufacturerData.CompanyId = 0xFFFE;

            // Finally set the data payload within the manufacturer-specific section
            // Here, use a 16-bit UUID: 0x1234 -> {0x34, 0x12} (little-endian)
            var writer = new DataWriter();
            UInt16 uuidData = 0x1234;
            writer.WriteUInt16(uuidData);

            // Make sure that the buffer length can fit within an advertisement payload. Otherwise you will get an exception.
            manufacturerData.Data = writer.DetachBuffer();

            // Add the manufacturer data to the advertisement publisher:
            publisher.Advertisement.ManufacturerData.Add(manufacturerData);

            //// Display the information about the published payload
            //PublisherPayloadBlock.Text = string.Format("Published payload information: CompanyId=0x{0}, ManufacturerData=0x{1}",
            //    manufacturerData.CompanyId.ToString("X"),
            //    uuidData.ToString("X"));

            //// Display the current status of the publisher
            //PublisherStatusBlock.Text = string.Format("Published Status: {0}, Error: {1}",
            //    publisher.Status,
            //    BluetoothError.Success);
        }

        /// <summary>
        /// Invoked as an event handler when the status of the publisher changes.
        /// </summary>
        /// <param name="publisher">Instance of publisher that triggered the event.</param>
        /// <param name="eventArgs">Event data containing information about the publisher status change event.</param>
        private async void OnPublisherStatusChanged(
            BluetoothLEAdvertisementPublisher publisher,
            BluetoothLEAdvertisementPublisherStatusChangedEventArgs eventArgs)
        {
            // This event handler can be used to monitor the status of the publisher.
            // We can catch errors if the publisher is aborted by the system
            BluetoothLEAdvertisementPublisherStatus status = eventArgs.Status;
            BluetoothError error = eventArgs.Error;

            // Update the publisher status displayed in the sample
            // Serialize UI update to the main UI thread
            await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                //PublisherStatusBlock.Text = string.Format("Published Status: {0}, Error: {1}",
                //    status.ToString(),
                //    error.ToString());
            });
        }

        private void publish_bt_Click(object sender, RoutedEventArgs e)
        {
            publisher_cb();
        }

        private void publish_bt_Copy_Click(object sender, RoutedEventArgs e)
        {
            if (publisher != null)
            {
                publisher.Start();
                publisher.StatusChanged += OnPublisherStatusChanged;
                //publisher.Advertisement.ServiceUuids.
            }
        }

        private async void service_bt_Click(object sender, RoutedEventArgs e)
        {
            BLEAdv bleadv = new BLEAdv();

            bleadv.create_serviceAsync();
            bleadv.create_notify_service();

            bleadv.publish();

            testbox.Text += "publish finish";
        }

        private async void service_list_bt_Click(object sender, RoutedEventArgs e)
        {
            service_testbox.Text += "==================\n";
            if (ble_flag == false)
            {
                //var ble_id = "BluetoothLE#BluetoothLE14:2d:27:f5:c1:6e-f8:f0:05:f3:5e:5f";
                if (ble_id == null)
                {
                    return;
                }
                //bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(rootPage.SelectedBleDeviceId);
                var bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(ble_id);
                
                // testbox1.Text = bluetoothLeDevice.ToString();
                if (bluetoothLeDevice != null)
                {
                    // BT_Code: GattServices returns a list of all the supported services of the device.
                    // If the services supported by the device are expected to change
                    // during BT usage, subscribe to the GattServicesChanged event.

                    foreach (var service in bluetoothLeDevice.GattServices)
                    {
                        var uuid = service.Uuid.ToString();
                        service_testbox.Text += uuid + "\n";
                    }
                }
                else
                {
                    service_testbox.Text += "connect false";
                }
            }

        }

        private async void write_bt_Click(object sender, RoutedEventArgs e)
        {
            if (csc_characteristic != null)
            {
                service_testbox.Text += "start write\n";
                
                var writer = new DataWriter();
                // Populate writer with data
                // ...
                writer.WriteString("hello world\n");
                GattCommunicationStatus result = await csc_characteristic.WriteValueAsync(writer.DetachBuffer());
                //if (result ==  )
                service_testbox.Text += "write\n";
                //await _notifyCharacteristic.NotifyValueAsync(writer.DetachBuffer());
                if (result == GattCommunicationStatus.Success)
                {
                    service_testbox.Text += "write success\n";
                }
                else
                {
                    service_testbox.Text += "write " + result.ToString() + "\n";
                }
            }

            //            var result = await selectedCharacteristic.WriteValueAsync(writeBuffer);

            //            if (result == GattCommunicationStatus.Success)
            //            {
            //                rootPage.NotifyUser("Successfully wrote value to device", NotifyType.StatusMessage);
            //            }
            //            else
            //            {
            //                rootPage.NotifyUser($"Write failed: {result}", NotifyType.ErrorMessage);
            //            }

        }
    }
}
